home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / t_sys5 / unixcpio.gz / unixnet.cpio / test_ec.c < prev    next >
C/C++ Source or Header  |  1994-07-11  |  8KB  |  365 lines

  1. /* Driver for 3COM Ethernet card */
  2.  
  3. #define    TIMER    20000    /* Timeout on transmissions */
  4.  
  5. #include <stdio.h>
  6. #include "global.h"
  7. #include "mbuf.h"
  8. #include "enet.h"
  9. #include "iface.h"
  10. #include "ec.h"
  11. #include "timer.h"
  12. #include "arp.h"
  13. #include "trace.h"
  14.  
  15. void ec0vec(),ec1vec(),ec2vec();
  16. void (*ecvec[])() = {ec0vec,ec1vec,ec2vec};
  17. struct ec ec[EC_MAX];        /* Per-controller info */
  18. unsigned nec = 0;
  19.  
  20.  
  21. /* Initialize interface */
  22. int
  23. ec_init(interface,bufsize)
  24. struct interface *interface;
  25. unsigned bufsize;    /* Maximum size of receive queue in PACKETS */
  26. {
  27.     register struct ec *ecp;
  28.     register unsigned base;
  29.     void eaudit();
  30.     unsigned short getcs();
  31.     int16 dev;
  32.  
  33.     dev = interface->dev;
  34.     ecp = &ec[dev];
  35.     base = ecp->base;
  36.     ecp->rcvmax = bufsize;
  37.     ecp->iface = interface;
  38.  
  39.     /* Pulse IE_RESET */
  40.      outportb(IE_CSR(base),IE_RESET);
  41.  
  42.     if(interface->hwaddr == NULLCHAR)
  43.         interface->hwaddr = malloc(EADDR_LEN);
  44.     getecaddr(base,interface->hwaddr);
  45.     setecaddr(base,interface->hwaddr);
  46.     if(memcmp(interface->hwaddr,ether_bdcst,EADDR_LEN) == 0){
  47.         printf("EC address PROM contains broadcast address!!\n");
  48.         return -1;
  49.     }
  50.     /* gain control of buffer */
  51.     outportb(IE_CSR(base),IE_SYSBFR);
  52.  
  53.     /* Set transmit detect bits */
  54.     outportb(EDLC_XMT(base),EDLC_16 | EDLC_JAM);
  55.  
  56.     /* Set up the receiver and flush status */
  57.     outportb(EDLC_RCV(base),EDLC_MULTI|EDLC_GOOD|EDLC_ANY|EDLC_SHORT
  58.      |EDLC_DRIBBLE|EDLC_FCS|EDLC_OVER);
  59.     inportb(EDLC_RCV(base));
  60.  
  61.     /* Start receiver */
  62.     outportw(IE_RP(base),0);    /* Reset read pointer */
  63.     outportb(IE_CSR(base),IE_RCVEDLC);
  64.     return 0;
  65. }
  66.  
  67. /* Send an IP datagram on Ethernet */
  68. int
  69. ec_send(bp,interface,gateway,precedence,delay,throughput,reliability)
  70. struct mbuf *bp;        /* Buffer to send */
  71. struct interface *interface;    /* Pointer to interface control block */
  72. int32 gateway;            /* IP address of next hop */
  73. char precedence;
  74. char delay;
  75. char throughput;
  76. char reliability;
  77. {
  78.     char *egate,*res_arp();
  79.  
  80.     egate = res_arp(interface,ARP_ETHER,gateway,bp);
  81.     if(egate != NULLCHAR)
  82.         return (*interface->output)(interface,egate,interface->hwaddr,IP_TYPE,bp);
  83.     return 0;
  84. }
  85.  
  86. /* Send a packet with Ethernet header */
  87. int
  88. ec_output(interface,dest,source,type,data)
  89. struct interface *interface;        /* Pointer to interface control block */
  90. char dest[];        /* Destination Ethernet address */
  91. char source[];        /* Source Ethernet address */
  92. int16 type;        /* Type field */
  93. struct mbuf *data;    /* Data field */
  94. {
  95.     struct ether ep;
  96.     struct mbuf *bp;
  97.  
  98.     memcpy(ep.dest,dest,EADDR_LEN);
  99.     memcpy(ep.source,source,EADDR_LEN);
  100.     ep.type = type;
  101.     if((bp = htonether(&ep,data)) == NULLBUF){
  102.         free_p(data);
  103.         return -1;
  104.     }
  105.     return (*interface->raw)(interface,bp);
  106. }
  107.  
  108. /* Send raw packet (caller provides header) */
  109. int
  110. ec_raw(interface,bp)
  111. struct interface *interface;    /* Pointer to interface control block */
  112. struct mbuf *bp;        /* Data field */
  113. {
  114.     register struct ec *ecp;
  115.     register unsigned base;
  116.     register int i;
  117.     short size;
  118.  
  119.     ecp = &ec[interface->dev];
  120.     base = ecp->base;
  121.  
  122.     ecp->estats.xmit++;
  123.     dump(interface,IF_TRACE_OUT,TRACE_ETHER,bp);
  124.  
  125.     size = len_mbuf(bp);
  126.     /* Pad the size out to the minimum, if necessary,
  127.      * with junk from the last packet (nice security hole here)
  128.      */
  129.     if(size < RUNT)
  130.         size = RUNT;
  131.     size = (size+1) & ~1;    /* round size up to next even number */
  132.  
  133.     /* Wait for transmitter ready, if necessary. IE_XMTBSY is valid
  134.      * only in the transmit mode, hence the initial check.
  135.      */
  136.     if((inportb(IE_CSR(base)) & IE_BUFCTL) == IE_XMTEDLC){
  137.         for(i=TIMER;(inportb(IE_CSR(base)) & IE_XMTBSY) && i != 0;i--)
  138.             ;
  139.         if(i == 0){
  140.             ecp->estats.timeout++;
  141.             free_p(bp);
  142.             return -1;
  143.         }
  144.     }
  145.     ecp->size = size;
  146.     /* Get control of the board buffer and disable receiver */
  147.     outportb(IE_CSR(base),IE_SYSBFR);
  148.     /* Point GP at beginning of packet */
  149.     outportw(IE_GP(base),BFRSIZ-size);
  150.     /* Actually load each piece with a fast assembler routine */
  151.     while(bp != NULLBUF){
  152.         outbuf(IE_BFR(base),bp->data,bp->cnt);
  153.         bp = free_mbuf(bp);
  154.     }
  155.     /* Start transmitter */
  156.     outportw(IE_GP(base),BFRSIZ-size);
  157.     outportb(IE_CSR(base),IE_XMTEDLC);
  158.     return 0;
  159. }
  160. ecint()
  161. {
  162. }
  163.  
  164. /* Service the Ethernet controller */
  165. void
  166. ec_recv(interface)
  167. struct interface *interface;
  168. {
  169.     register struct ec *ecp;
  170.     register unsigned base;
  171.     struct mbuf *bp;
  172.     int16 size;
  173.     char stat;
  174.     void arp_input();
  175.     int ip_route();
  176.     struct ether hdr;
  177.     char multicast;
  178.  
  179.     ecp = &ec[interface->dev];
  180.     base = ec[interface->dev].base;
  181.  
  182.     /* Check for transmit jam */
  183.     if(!(inportb(IE_CSR(base)) & IE_XMTBSY)){
  184.         stat = inportb(EDLC_XMT(base));
  185.         if(stat & EDLC_16){
  186.             ecp->estats.jam16++;
  187.             rcv_fixup(base);
  188.         } else if(stat & EDLC_JAM){
  189.             /* Crank counter back to beginning and restart transmit */
  190.             ecp->estats.jam++;
  191.             outportb(IE_CSR(base),IE_SYSBFR);
  192.             outportw(IE_GP(base),BFRSIZ - ecp->size);
  193.             outportb(IE_CSR(base),IE_XMTEDLC);
  194.         }
  195.     }
  196. #ifdef    foo
  197.     if(inportb(IE_CSR(base)) & IE_RCVBSY)
  198.         return;
  199. #endif
  200.     for(;;){
  201.         stat = inportb(EDLC_RCV(base));
  202.         if(stat & EDLC_STALE)
  203.             break;
  204.  
  205.         if(stat & EDLC_OVER){
  206.             ecp->estats.over++;
  207.             rcv_fixup(base);
  208.             continue;
  209.         }
  210.         if(stat & (EDLC_SHORT | EDLC_FCS | EDLC_DRIBBLE)){
  211.             ecp->estats.bad++;
  212.             rcv_fixup(base);
  213.             continue;
  214.         }
  215.         if(stat & EDLC_ANY){
  216.             /* Get control of the buffer */
  217.             outportw(IE_GP(base),0);
  218.             outportb(IE_CSR(base),IE_SYSBFR);
  219.         
  220.             /* Allocate mbuf and copy the packet into it */
  221.             size = inportw(IE_RP(base));
  222.             if(size < RUNT || size > GIANT)
  223.                 ecp->estats.bad++;
  224.             else if((bp = alloc_mbuf(size)) == NULLBUF)
  225.                 ecp->estats.nomem++;
  226.             else {
  227.                 ecp->estats.recv++;
  228.                 inbuf(IE_BFR(base),bp->data,size);
  229.                 bp->cnt = size;
  230.  
  231.                 dump(interface,IF_TRACE_IN,TRACE_ETHER,bp);
  232.  
  233.                 /* Remove Ethernet header and kick packet upstairs */
  234.                 ntohether(&hdr,&bp);
  235.                 if(hdr.dest[0] & 1)
  236.                     multicast = 1;
  237.                 else
  238.                     multicast = 0;
  239.                 switch(hdr.type){
  240.                 case ARP_TYPE:
  241.                     arp_input(interface,bp);
  242.                     break;
  243.                 case IP_TYPE:
  244.                     ip_route(bp,multicast);
  245.                     break;
  246.                 default:
  247.                     free_p(bp);
  248.                     break;
  249.                 }
  250.             }
  251.             outportb(IE_CSR(base),IE_RCVEDLC);
  252.             outportb(IE_RP(base),0);
  253.         }
  254.     }
  255. }
  256. static
  257. rcv_fixup(base)
  258. register unsigned base;
  259. {
  260.     outportb(IE_CSR(base),IE_SYSBFR);
  261.     outportb(IE_CSR(base),IE_RCVEDLC);
  262.     outportb(IE_RP(base),0);
  263. }
  264. /* Read Ethernet address from controller PROM */
  265. static
  266. getecaddr(base,cp)
  267. register unsigned base;
  268. register char *cp;
  269. {
  270.     register int i;
  271.  
  272.     for(i=0;i<EADDR_LEN;i++){
  273.         outportw(IE_GP(base),i);
  274.         *cp++ = inportb(IE_SAPROM(base));
  275.     }
  276. }
  277. /* Set Ethernet address on controller */
  278. static
  279. setecaddr(base,cp)
  280. register unsigned base;
  281. register char *cp;
  282. {
  283.     register int i;
  284.  
  285.     for(i=0;i<EADDR_LEN;i++)
  286.         outportb(EDLC_ADDR(base)+i,*cp++);
  287. }
  288. /* Shut down the Ethernet controller */
  289. ec_stop(interface)
  290. struct interface *interface;
  291. {
  292.     register unsigned base;
  293.     int16 dev;
  294.  
  295.     dev = interface->dev;
  296.     base = ec[dev].base;
  297.  
  298.     /* Pulse IE_RESET */
  299.     outportb(IE_CSR(base),IE_RESET);
  300.     outportb(IE_CSR(base),0);
  301. }
  302. /* Attach a 3-Com model 3C500 Ethernet controller to the system
  303.  * argv[0]: hardware type, must be "3c500"
  304.  * argv[1]: I/O address, e.g., "0x300"
  305.  * argv[2]: vector, e.g., "3"
  306.  * argv[3]: mode, must be "arpa"
  307.  * argv[4]: interface label, e.g., "ec0"
  308.  * argv[5]: maximum number of packets allowed on receive queue, e.g., "5"
  309.  * argv[6]: maximum transmission unit, bytes, e.g., "1500"
  310.  */
  311. ec_attach(argc,argv)
  312. int argc;
  313. char *argv[];
  314. {
  315.     register struct interface *if_ec;
  316.     extern struct interface *ifaces;
  317.     unsigned dev;
  318.     int ec_init();
  319.     int ec_send();
  320.     void ec_recv();
  321.     int ec_stop();
  322.     int pether(),gaether();
  323.  
  324.     arp_init(ARP_ETHER,EADDR_LEN,IP_TYPE,ARP_TYPE,ether_bdcst,pether,gaether);
  325.     if(nec >= EC_MAX){
  326.         printf("Too many Ethernet controllers\n");
  327.         return -1;
  328.     }
  329.     dev = nec++;
  330.     if((if_ec = (struct interface *)calloc(1,sizeof(struct interface))) == NULLIF
  331.      ||(if_ec->name = malloc((unsigned)strlen(argv[4])+1)) == NULLCHAR){
  332.         printf("ec_attach: no memory!\n");
  333.         return -1;
  334.     }
  335.     strcpy(if_ec->name,argv[4]);
  336.     if_ec->mtu = atoi(argv[6]);
  337.     if_ec->send = ec_send;
  338.     if_ec->output = ec_output;
  339.     if_ec->raw = ec_raw;
  340.     if_ec->recv = ec_recv;
  341.     if_ec->stop = ec_stop;
  342.     if_ec->dev = dev;
  343.  
  344.     ec[dev].base = htoi(argv[1]);
  345.     ec[dev].vec = htoi(argv[2]);
  346.  
  347.     if(strcmp(argv[3],"arpa") != 0){
  348.         printf("Mode %s unknown for interface %s\n",
  349.             argv[3],argv[4]);
  350.         free(if_ec->name);
  351.         free((char *)if_ec);
  352.         return -1;
  353.     }
  354.     /* Initialize device */
  355.     if(ec_init(if_ec,(unsigned)atoi(argv[5])) != 0){
  356.         free(if_ec->name);
  357.         free((char *)if_ec);
  358.         return -1;
  359.     }
  360.     if_ec->next = ifaces;
  361.     ifaces = if_ec;
  362.  
  363.     return 0;
  364. }
  365.